/* project:			package:		class:			credits:					date:
 * GuildMaster		tools			StringTools		by Dolraith & Kirenno		Aug 2011
 * -- contains information needed to skin the application and related methods
 * 
 * === PUBLIC FNs ===================================================================
 * 	
 * 	public static int convertStrToInt (String str)					-- returns int value of str or -1 if parser fails
 *  public static int convertStrToInt (String str, int false_value)	-- returns int value of str or false_value if parser fails
 * 	public static double convertStrToDouble (String str)			-- returns double value of str or -1 if parser fails
 * 	public static double convertStrToDouble (String str, double false_value) -- returns double value of str or false_value if parser fails
 * 
 * 	public static String clearComments (String str)		-- cuts off commented pieces (if any)
 */

package tools;

import java.util.LinkedList;

public class StringTools {
	
	// === CONVERTERS =============================================================================

	public static int convertStrToInt (String str) {						// returns int value of str or -1 if parser fails
		return convertStrToInt (str, -1);	
	}
	public static int convertStrToInt (String str, int false_value) {		// returns int value of str or false_value if parser fails
		str = str.trim();
		try { 
			return Integer.parseInt(str);  
		} catch (NumberFormatException nfe) {
			System.out.println("ERROR in tools.StringTools.convertStrToInt(String,int): cannot parse '" + str + "'. Returned " + false_value + " for lack of a better option.");
			return false_value;
		}
	}
	public static double convertStrToDouble (String str) {					// returns double value of str or -1 if parser fails
		return convertStrToDouble (str, -1);
	}
	public static double convertStrToDouble (String str, double false_value) {//returns double value of str or false_value if parser fails
		str = str.trim();
		try { 
			return Double.parseDouble(str);  
		} catch (NumberFormatException nfe) {
			System.out.println("ERROR in tools.StringTools.convertStrToDouble(String,double): cannot parse '" + str + "'. Returned " + false_value + " for lack of a better option.");
			return false_value;
		}
	}
	
	// === = ======================================================================================
	public static String clearComments (String str) {						// returns the string with all comments cut out; comment tokens: // or /* */
		// TODO fix multi-line comments.... somehow
		
		int pos = 0;												// current position
		
		LinkedList <Integer> quotes = new LinkedList <Integer> ();	// a list of positions of " chars in the string
		while (str.indexOf("\"", pos) > -1) {							// while there are " after pos in the str
			quotes.add(str.indexOf("\"", pos));							// record the position of "
			pos = quotes.getLast()+1;									// advance position to next character
		}
		
		pos = 0;														// reset current position
		while ((str.indexOf("//", pos) > -1) || (str.indexOf("/*", pos) > -1)) {
			int commentPos = str.indexOf("//", pos);					// find the location of the next comment token
			if (commentPos == -1)										//		either // or /*, whatever happens first
				commentPos = str.indexOf("/*", pos);
			else if (str.indexOf("/*", pos) > -1)
				if (commentPos > str.indexOf("/*", pos))
					commentPos = str.indexOf("/*", pos);
				
			
			int quotePos = 0;											// find the position (in quotes list) of the " occuring
			for (int i=0; i < quotes.size(); i++)						// 		right after the comment token
				if (quotes.get(i) > commentPos) {
					quotePos = i;
					break;
				}
			
			if ((quotePos%2==0) || (quotePos == quotes.size()-1))		// if there is an even number of quote marks before this token -
			{															// or if odd, the odd mark has no pair at all - then this is a true comment
				if (str.startsWith("//", commentPos)) {						// if this is a single mark comment (//)
					return str.substring(0,commentPos);						// cut off everything after the comment mark
				} else {													// else this is a open-close comment (/*  */)
					int closing = str.indexOf("*/", commentPos);			// find where the comment closes after the opening token
					if (closing == -1) {										// if no closing token is found
						pos = commentPos+2;										// adjust position and dismiss this token as fake
						continue;
					} else {													// if found comment closing token
						str = str.substring(0,commentPos).concat(str.substring(closing+2));	// cut out the comment
						int commentLength = (closing+2) - commentPos;
						for (int i=0; i < quotes.size(); i++)					// and adjust all quote positions
							if (quotes.get(i) > commentPos) {						// if quote position was after the comment token
								if (quotes.get(i)-commentLength < 0)				// and was inside the comment		
									quotes.remove(i);								// drop this quote position from list
								else quotes.set(i, quotes.get(i)-commentLength);	// if it was after comment and not inside, adjsut
							}
					}
				}
			} else {													// if there is an unclosed " preceding token that closes later
				pos = commentPos + 2;										// then ignore this comment token since its part of an inset string value
				continue;
			}
			
		}
		return str;
	}
}
